import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import type { Notification, NotificationFilterParams } from '@/types/notification'
import {
  getNotifications,
  getUnreadCount,
  markNotificationAsRead,
  markAllNotificationsAsRead,
  deleteNotification,
  deleteBatchNotifications
} from '@/api/notification'
import { storageManager } from '@/utils/storage'
import { useUserStore } from '@/stores/user'

export const useNotificationStore = defineStore('notification', () => {
  // 状态
  const notifications = ref<Notification[]>([])
  const unreadCount = ref<number>(0)
  const loading = ref<boolean>(false)
  const total = ref<number>(0)
  const currentPage = ref<number>(1)
  const pageSize = ref<number>(20)
  const filterParams = ref<NotificationFilterParams>({})
  
  // SSE 连接
  let eventSource: EventSource | null = null
  let reconnectTimer: ReturnType<typeof setTimeout> | null = null
  const reconnectDelay = 3000 // 3秒后重连
  let isRefreshingToken = false // token刷新中标识

  // 计算属性
  const hasUnread = computed(() => unreadCount.value > 0)
  const unreadNotifications = computed(() => 
    notifications.value.filter(n => !n.is_read)
  )

  /**
   * 获取通知列表
   */
  // 防止重复请求的标识
  let fetchingPromise: Promise<void> | null = null
  
  const fetchNotifications = async (params?: NotificationFilterParams) => {
    // 如果正在请求中，等待当前请求完成
    if (fetchingPromise) {
      return fetchingPromise
    }
    
    fetchingPromise = (async () => {
      try {
        loading.value = true
        const queryParams = {
          page: currentPage.value,
          limit: pageSize.value,
          ...filterParams.value,
          ...params
        }
        
        const response = await getNotifications(queryParams)
        
        if (response?.success) {
          // 后端返回格式：{ success: true, data: [...], pagination: { total, page, size, pages, has_prev, has_next } }
          // data 是数组，pagination 是顶级字段
          const responseData = response as any
          
          // 更新通知列表
          if (Array.isArray(responseData.data)) {
            notifications.value = responseData.data
          } else {
            notifications.value = []
          }
          
          // 更新分页信息（后端返回标准分页结构）
          if (responseData.pagination) {
            total.value = Number(responseData.pagination.total ?? 0)
            currentPage.value = Number(responseData.pagination.page ?? currentPage.value)
            pageSize.value = Number(responseData.pagination.size ?? pageSize.value)
          } else {
            // 如果没有 pagination，使用默认值
            total.value = notifications.value.length
            // 如果传入了分页参数，使用传入的参数
            if (params?.page !== undefined) {
              currentPage.value = params.page
            }
            if (params?.limit !== undefined) {
              pageSize.value = params.limit
            }
          }
          
          // 保存筛选参数（排除分页参数）
          if (params) {
            const { page, limit, ...otherParams } = params
            filterParams.value = { ...filterParams.value, ...otherParams }
          }
        } else {
          // 如果响应不成功，清空列表
          notifications.value = []
          total.value = 0
        }
      } catch (error) {
        console.error('获取通知列表失败:', error)
      } finally {
        loading.value = false
        fetchingPromise = null
      }
    })()
    
    return fetchingPromise
  }

  /**
   * 获取未读通知数量
   */
  const fetchUnreadCount = async () => {
    try {
      const response = await getUnreadCount()
      if (response.data) {
        unreadCount.value = response.data.count || 0
      }
    } catch (error) {
      console.error('获取未读通知数量失败:', error)
    }
  }

  /**
   * 标记通知为已读
   */
  const markAsRead = async (notificationId: string) => {
    try {
      await markNotificationAsRead(notificationId)
      
      // 更新本地状态
      const notification = notifications.value.find(n => n.id === notificationId)
      if (notification && !notification.is_read) {
        notification.is_read = true
        notification.read_at = new Date().toISOString()
        unreadCount.value = Math.max(0, unreadCount.value - 1)
      }
    } catch (error) {
      console.error('标记通知为已读失败:', error)
      throw error
    }
  }

  /**
   * 标记所有通知为已读
   */
  const markAllAsRead = async () => {
    try {
      const response = await markAllNotificationsAsRead()
      
      // 更新本地状态
      notifications.value.forEach(n => {
        if (!n.is_read) {
          n.is_read = true
          n.read_at = new Date().toISOString()
        }
      })
      unreadCount.value = 0
      
      return response.data?.count || 0
    } catch (error) {
      console.error('标记所有通知为已读失败:', error)
      throw error
    }
  }

  /**
   * 删除通知
   */
  const removeNotification = async (notificationId: string) => {
    try {
      await deleteNotification(notificationId)
      
      // 更新本地状态
      const index = notifications.value.findIndex(n => n.id === notificationId)
      if (index > -1) {
        const notification = notifications.value[index]
        if (!notification.is_read) {
          unreadCount.value = Math.max(0, unreadCount.value - 1)
        }
        notifications.value.splice(index, 1)
        total.value = Math.max(0, total.value - 1)
      }
    } catch (error) {
      console.error('删除通知失败:', error)
      throw error
    }
  }

  /**
   * 批量删除通知
   */
  const removeBatchNotifications = async (notificationIds: string[]) => {
    try {
      const response = await deleteBatchNotifications(notificationIds)
      
      // 更新本地状态
      const deletedCount = response.data?.count || 0
      const deletedUnreadCount = notifications.value.filter(
        n => notificationIds.includes(n.id) && !n.is_read
      ).length
      
      notifications.value = notifications.value.filter(
        n => !notificationIds.includes(n.id)
      )
      total.value = Math.max(0, total.value - deletedCount)
      unreadCount.value = Math.max(0, unreadCount.value - deletedUnreadCount)
      
      return deletedCount
    } catch (error) {
      console.error('批量删除通知失败:', error)
      throw error
    }
  }

  /**
   * 连接 SSE 通知流
   */
  const connectStream = async () => {
    // 如果已经连接，先断开
    if (eventSource) {
      return
    }
    
    const userStore = useUserStore()
    
    // 在连接前，检查并刷新 token（如果即将过期）
    try {
      // 尝试刷新 token（如果即将过期）
      if (userStore.token && !userStore.isTokenValid()) {
        console.log('Token已过期，尝试刷新...')
        await userStore.refreshTokenIfNeeded()
      } else {
        // 即使 token 有效，也尝试刷新（如果即将过期）
        await userStore.refreshTokenIfNeeded(5).catch(() => {
          // 刷新失败不影响连接
        })
      }
    } catch (error) {
      console.error('刷新token失败:', error)
      // 如果刷新失败，仍然尝试连接（可能token仍然有效）
    }
    
    // 获取最新的 token
    const token = userStore.token || storageManager.getItem('token')
    if (!token || typeof token !== 'string') {
      console.warn('未找到 token，无法连接通知流')
      return
    }
    
    // 构建 SSE URL（EventSource 不支持自定义 headers，需要通过查询参数传递 token）
    const baseURL = import.meta.env.VITE_API_BASE_URL || '/api/v1'
    const apiBase = baseURL.endsWith('/') ? baseURL.slice(0, -1) : baseURL
    const url = `${apiBase}/notifications/stream?token=${encodeURIComponent(token)}`
    
    try {
      // 创建 EventSource 连接
      eventSource = new EventSource(url)
      
      // 监听消息
      eventSource.onmessage = (event) => {
        try {
          const data = JSON.parse(event.data)
          
          switch (data.type) {
            case 'unread_count':
              // 更新未读数量
              unreadCount.value = data.count || 0
              break
              
            case 'new_notification':
              // 新增通知
              if (data.notification) {
                const notification = data.notification as Notification
                // 如果当前在列表页面，添加到列表顶部
                if (notifications.value.length > 0) {
                  notifications.value.unshift(notification)
                  total.value += 1
                }
              }
              break
              
            case 'notification_updated':
              // 更新通知
              if (data.notification) {
                const notification = data.notification as Notification
                const index = notifications.value.findIndex(n => n.id === notification.id)
                if (index > -1) {
                  notifications.value[index] = notification
                }
              }
              break
              
            case 'notification_deleted':
              // 删除通知
              if (data.notification_id) {
                const index = notifications.value.findIndex(n => n.id === data.notification_id)
                if (index > -1) {
                  const notification = notifications.value[index]
                  if (!notification.is_read) {
                    unreadCount.value = Math.max(0, unreadCount.value - 1)
                  }
                  notifications.value.splice(index, 1)
                  total.value = Math.max(0, total.value - 1)
                }
              }
              break
              
            case 'heartbeat':
              // 心跳，保持连接
              break
              
            case 'error':
              console.error('通知流错误:', data.message)
              // 检查是否是 token 过期错误
              const errorMessage = (data.message || '').toLowerCase()
              if (errorMessage.includes('expired') || errorMessage.includes('401') || errorMessage.includes('unauthorized')) {
                console.log('检测到token过期错误，尝试刷新token并重连...')
                handleTokenExpired()
              }
              break
          }
        } catch (error) {
          console.error('解析通知流消息失败:', error)
        }
      }
      
      // 监听错误
      eventSource.onerror = async (error) => {
        // EventSource 在连接失败时会触发 onerror
        // 但是无法直接获取 HTTP 状态码，需要根据实际情况判断
        console.warn('通知流连接错误，尝试刷新token并重连...', error)
        
        // 断开连接
        disconnectStream()
        
        // 尝试刷新 token 并重连
        await handleTokenExpired()
      }
      
      // 连接打开
      eventSource.onopen = () => {
        // 清除重连定时器
        if (reconnectTimer) {
          clearTimeout(reconnectTimer)
          reconnectTimer = null
        }
        console.log('通知流连接已建立')
      }
    } catch (error) {
      console.error('创建通知流连接失败:', error)
    }
  }

  /**
   * 处理 token 过期的情况
   */
  const handleTokenExpired = async () => {
    // 如果正在刷新 token，等待完成
    if (isRefreshingToken) {
      // 如果已经在刷新，等待一段时间后重连
      reconnectTimer = setTimeout(() => {
        connectStream()
      }, reconnectDelay)
      return
    }
    
    isRefreshingToken = true
    
    try {
      const userStore = useUserStore()
      
      // 尝试刷新 token
      const refreshSuccess = await userStore.refreshTokenIfNeeded()
      
      if (refreshSuccess && userStore.isTokenValid()) {
        console.log('Token刷新成功，重新连接通知流...')
        // Token 刷新成功，立即重新连接
        await connectStream()
      } else {
        console.warn('Token刷新失败或仍然无效，延迟重连...')
        // Token 刷新失败，延迟重连（可能用户已退出登录）
        reconnectTimer = setTimeout(() => {
          connectStream()
        }, reconnectDelay * 2) // 失败后延迟更长时间
      }
    } catch (error) {
      console.error('处理token过期时出错:', error)
      // 发生错误，延迟重连
      reconnectTimer = setTimeout(() => {
        connectStream()
      }, reconnectDelay * 2)
    } finally {
      isRefreshingToken = false
    }
  }

  /**
   * 断开 SSE 连接
   */
  const disconnectStream = () => {
    if (eventSource) {
      eventSource.close()
      eventSource = null
    }
    if (reconnectTimer) {
      clearTimeout(reconnectTimer)
      reconnectTimer = null
    }
    // 注意：不重置 isRefreshingToken，让正在进行的刷新完成
  }

  /**
   * 重置状态
   */
  const reset = () => {
    notifications.value = []
    unreadCount.value = 0
    total.value = 0
    currentPage.value = 1
    filterParams.value = {}
    disconnectStream()
  }

  return {
    // 状态
    notifications,
    unreadCount,
    loading,
    total,
    currentPage,
    pageSize,
    filterParams,
    
    // 计算属性
    hasUnread,
    unreadNotifications,
    
    // 方法
    fetchNotifications,
    fetchUnreadCount,
    markAsRead,
    markAllAsRead,
    removeNotification,
    removeBatchNotifications,
    connectStream,
    disconnectStream,
    reset,
    
    // 分页方法
    setPage: (page: number) => {
      currentPage.value = page
    },
    setPageSize: (size: number) => {
      pageSize.value = size
      currentPage.value = 1 // 改变每页数量时重置到第一页
    },
    goToPage: async (page: number) => {
      currentPage.value = page
      await fetchNotifications({ page })
    },
    changePageSize: async (size: number) => {
      pageSize.value = size
      currentPage.value = 1
      await fetchNotifications({ page: 1, limit: size })
    }
  }
})

